package projectx.core.dao.dto;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

public class DynamicDTO implements Serializable {

	private static final String LINE_END = "\n";
	
    private HashMap _map = null;

    /**
     *   コンストラクタ <BR>
     */
    public DynamicDTO (){
        _map = new HashMap();
    }

    /**
     *  キーと値のマッピングの数を返します。 <BR>
     *
     *   @return    int     数
     */
    public int size() {
        return _map.size();
    }

    /**
     *  キーに対する値のマッピングの数を返します。 <BR>
     *
     *   @param     key    キー
     *   @return    int    数
     */
    public int size(String key) {
        if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            return lst.size();
        }
        return 0;
    }

    /**
     *  キーに対する値が存在するかをチェック。 <BR>
     *
     *   @param     key        キー
     *   @return    boolean    true:正常 false:異常
     */
    public boolean isKey(String key) {
        if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            if(lst.size()>0) {
              return true;
            }
        }
        return false;
    }

    /**
     *  キーと値を追加する。 <BR>
     *
     *   @param     key        キー
     *   @param     val        値
     */
    public void add(String key, String val) {
        if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            lst.add(val);
        }
        else {
            ArrayList lst = new ArrayList();
            lst.add(val);
            _map.put(key, lst);
        }
    }

    /**
     *  指定された位置にキーと値を追加する。 <BR>
     *
     *   @param     idx        追加する位置のインデックス
     *   @param     key        キー
     *   @param     val        値
     */
    public void add(int idx, String key, String val) {
    	int tempIdx = idx;

        if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            if(tempIdx<0 || tempIdx>lst.size()) {
            	tempIdx = lst.size();
            }
            lst.add(tempIdx, val);
        }
        else {
            ArrayList lst = new ArrayList();
            lst.add(val);
            _map.put(key, lst);
        }
    }

    /**
     *  キーに対する値を取得する。 <BR>
     *
     *   @param     key        キー
     *   @return    String     値
     */
    public String get(String key) {
        ArrayList lst = (ArrayList)_map.get(key);
        if(lst!=null && lst.size()>0) {
            String val = (String)lst.get(0);
            return val;
        }
        return null;
    }

    /**
     *  指定された位置のキーに対する値を取得する。 <BR>
     *
     *   @param     key        キー
     *   @param     idx        取得する位置のインデックス
     *   @return    String     値
     */
    public String get(String key, int idx) {
        ArrayList lst = (ArrayList)_map.get(key);
        if(lst!=null) {
            if(idx>=0 && idx<lst.size()) {
                String val = (String)lst.get(idx);
                return val;
            }
        }
        return null;
    }

    /**
     *  キーに対する値を取得する。 <BR>
     *
     *   @param     key        キー
     *   @param     defStr     値の初期値
     *   @return    String     値
     */
    public String get(String key, String defStr) {
        String val = get(key);
        if(val==null) {
          val = defStr;
        }
        return val;
    }

    /**
     *  指定された位置のキーに対する値を取得する。 <BR>
     *
     *   @param     key        キー
     *   @param     idx        取得する位置のインデックス
     *   @param     defStr     値の初期値
     *   @return    String     値
     */
    public String get(String key, int idx, String defStr) {
        String val = get(key, idx);
        if(val==null) {
          val = defStr;
        }
        return val;
    }

    /**
     *  キーに対する値を削除する。 <BR>
     *
     *   @param     key        キー
     */
    public void remove(String key) {
        _map.remove(key);
    }

    /**
     *  指定された位置のキーに対する値を削除する。 <BR>
     *
     *   @param     key        キー
     *   @param     idx        削除する位置のインデックス
     */
    public void remove(String key,int idx) {
        if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            if(idx<0 && idx>=lst.size()) {
                return;
            }

            lst.remove(idx);
        }
    }

    /**
     *  指定された位置にキーと値をセットする。 <BR>
     *   セットする位置のインデックスが現在のデータ個数を越えていた場合は<BR>
     *   そのINDEXになるまでnullを追加する<BR>
     *
     *   @param     idx        セットする位置のインデックス
     *   @param     key        キー
     *   @param     val        値
     */
    public void set(int idx, String key, String val) {
        if(!_map.containsKey(key)) {
            ArrayList lst = new ArrayList();
            _map.put(key, lst);
        }

        ArrayList lst = (ArrayList)_map.get(key);
        if(idx<0){
            lst.add(val);
            return;
        }

        if(idx>=lst.size()) {
            //指定INDEXまでダミーデータを追加
            int sidx = lst.size();
            while(sidx<idx){
                sidx++;
                lst.add(null);
            }
            lst.add(val);
            return;
        }
        
        lst.set(idx, val);

        /*try {
            lst.set(idx, val);
        } catch(IndexOutOfBoundsException e) {
        }*/
    }

    /**
     *  キーと値をセットする。 <BR>
     *
     *   @param     key        キー
     *   @param     val        値
     */
    public void set(String key, String val) {
        set(0, key, val);
    }

    /**
     *  キーと値をセットする。 <BR>
     *
     *   @param     key        キー
     *   @param     val        値の配列
     */
    public void set(String key, String[] val) {
        /*if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            lst.clear();
            if(val!=null) {
                for(int i=0; i<val.length; i++) {
                    lst.add(val[i]);
                }
            }
        }else {
            if(val!=null) {
                for(int i=0; i<val.length; i++) {
                    add(key, val[i]);
                }
            }
        }*/
    	
    	if(_map.containsKey(key)) {
            ArrayList lst = (ArrayList)_map.get(key);
            lst.clear();
    	}
        if(val!=null) {
            for(int i=0; i<val.length; i++) {
                add(key, val[i]);
            }
        }
    }

    /**
     *  キーに対する値の配列を取得する。 <BR>
     *
     *   @param     key        キー
     *   @return    String[]   値の配列
     */
    public String[] toArray(String key) {
        ArrayList lst = (ArrayList)_map.get(key);
        if(lst!=null) {
            String[] strs = new String[lst.size()];
            lst.toArray(strs);
            return strs;
        }
        return new String[0];
    }

    /**
     *  キーの反復子を取得する。 <BR>
     *
     *   @return    Iterator   キーの反復子
     */
    public Iterator iterator() {
        //iterator = map.keySet().iterator();
        return _map.keySet().iterator();
        //return this;
    }

    /**
     *  Exceptionを発生させる。 <BR>
     *
     */
    public void remove() {
        throw new UnsupportedOperationException();
    }

    /**
     *  保持されているデータの取得。 <BR>
     *
     *   @return    String   キー、値の全要素
     */
    public String printAll() {
        StringBuffer buf = new StringBuffer();
        buf.append("DataBean (").append(size()).append(")").append(LINE_END);
        Iterator it = iterator();
        while(it.hasNext()) {
            String key = (String)it.next();
            if(size(key)>1) {
                String[] lst = toArray(key);
                for(int j=0; j<lst.length; j++) {
                    buf.append(key);
                    buf.append("[");
                    buf.append(j);
                    buf.append("] : ");
                    buf.append(lst[j]);
                    buf.append(LINE_END);
                }
            } else {
                buf.append(key);
                buf.append(" : ");
                buf.append(get(key));
                buf.append(LINE_END);
            }
        }
        return buf.toString();
    }

    /**
     *  保持されているデータの取得。 <BR>
     *
     *   @return    String   キー、値の全要素
     */
    public String printAllSort() {
        StringBuffer buf = new StringBuffer();
        buf.append("DataBean (").append(size()).append(")").append(LINE_END);

        Iterator it = iterator();
        Vector vec  = new Vector();
        while(it.hasNext()) {
            String key = (String)it.next();
            vec.addElement(key);
        }

        String[] keys = (String[])vec.toArray(new String[0]);
        if(keys==null){
        	return "";
        }
        if(keys.length>0){
            Arrays.sort(keys);
        }
        for( int ct=0;ct<keys.length;ct++){
            String key = keys[ct];
            if(size(key)>1) {
                String[] lst = toArray(key);
                for(int j=0; j<lst.length; j++) {
                    buf.append(key);
                    buf.append("[");
                    buf.append(j);
                    buf.append("] : ");
                    buf.append(lst[j]);
                    buf.append(LINE_END);
                }
            } else {
                buf.append(key);
                buf.append(" : ");
                buf.append(get(key));
                buf.append(LINE_END);
            }
        }
        return buf.toString();
    }
}
